package cn.rongbiz.peter.counter;

import org.opencv.core.*;
import org.opencv.core.Point;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgproc.Moments;
import org.opencv.videoio.VideoCapture;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SmartCounter {

    public static final ExecutorService executor = Executors.newScheduledThreadPool(10);

    private static final int MAX_VALUE = 255;
    private static final int MAX_VALUE_H = 360 / 2;
    private static final String MAIN_WINDOW = "计算机视觉检测-数量统计(测试)";
    private static final String ADJUST_WINDOW = "计算机视觉检测-参数调整";
    private static final String LOW_H_NAME = "LowH: ";
    private static final String LOW_S_NAME = "LowS: ";
    private static final String LOW_V_NAME = "LowV: ";
    private static final String HIGH_H_NAME = "HighH: ";
    private static final String HIGH_S_NAME = "HighS: ";
    private static final String HIGH_V_NAME = "HighV: ";
    private static final String STD_AREA = "StdA: ";


    private JSlider sliderLowH;
    private JSlider sliderHighH;
    private JSlider sliderLowS;
    private JSlider sliderHighS;
    private JSlider sliderLowV;
    private JSlider sliderHighV;
    private JSlider sliderStdArea;


    private JFrame mainWindow;
    private JDialog adjustWindow;

    private JLabel srcImageLabel;
    private JLabel detectImageLabel;
    private JLabel distImageLabel;

    private Random randColor = new Random();


    private int minArea = 100;
    private int maxArea = 10000;


    //    private static String defaultFilename = "image/img3.jpg";
    private static String NATIVE_LIBRARY_NAME = "CvSmartCounter";
    private static String rongLogoPath = "image/rongLogo.jpg";
    private static String company = "青岛容商天下网络有限公司";
    private static String copyrightInfo = "  ©2021  " + company + "  @copyright 版权所有  ";


    private AdjustChangeListener changeListener = new AdjustChangeListener();
    private AdjustMouseAdapter mouseAdapter = new AdjustMouseAdapter();
    private PopupMenuMouseListener popupMenuMouseListener = new PopupMenuMouseListener();
    private FileOptionListener fileOptionListener = new FileOptionListener();
    private MainMenuBar mainMenuBar = new MainMenuBar();


    private JPopupMenu adjustPopupMenu;
    //    private String currentFilePath = defaultFilename;
    /*处理状态栏*/
    private JComboBox currentPathComboBox;
    private JTextField groupCountField;
    private JTextField totalCountField;
    private JButton handleFileButton;
    private JButton chooseFileButton;

    /*菜单栏*/
    private JMenuItem chooseMenuItem;
    private JMenuItem exitMunuItem;
    /*弹出菜单栏*/
    private JMenuItem chooseFilePopuMenu;
    private JMenuItem handleFilePopuMenu;

    /*文件选择器*/
    private JFileChooser fileChooser;

    private final Dimension screenSize;
    private double viewPortWidth;
    private double viewPortHeight;
    private int imgPortWidth;
    private int imgPortHeight;

    private final Image scaledIcon;

    private JCheckBox recordCheckBox;
    private JCheckBox tipsCheckBox;
    private HookThread hookThread = new HookThread();

    private FileOutputStream csvFileOutStream;
    private FileNameExtensionFilter fileFilter;
    private JProgressBar progressBar;
    private JLabel progressLabel;
    private JMenuItem handleOptionItem;
    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分SS秒");


    public static void main(String[] args) {
        System.loadLibrary(NATIVE_LIBRARY_NAME);
        SmartCounter smartCounter = new SmartCounter();
        Runtime.getRuntime().addShutdownHook(smartCounter.hookThread);
        smartCounter.run();
    }

    public SmartCounter() {
        screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        viewPortWidth = screenSize.getWidth() * 0.8;
        viewPortHeight = screenSize.getHeight() * 0.8;

        ImageIcon icon = new ImageIcon(rongLogoPath);
        scaledIcon = icon.getImage().getScaledInstance(icon.getIconWidth() / 3, icon.getIconHeight() / 3, Image.SCALE_DEFAULT);

        fileFilter = new FileNameExtensionFilter(".jpg;.png;.jpeg", "jpg", "png", "jpeg");
        fileChooser = new JFileChooser(".");
        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
//        fileChooser.setSelectedFile(new File(defaultFilename));
        fileChooser.setDragEnabled(true);
//        fileChooser.setFileFilter(new ImageFileFilter());
        fileChooser.setFileFilter(fileFilter);

        LocalDate localDateNow = LocalDate.now();
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMdd");
        File recordFloder = new File("record");
        if (!recordFloder.exists()) {
            recordFloder.mkdir();
        }
        try {
            String dataTimes = localDateNow.format(format);
            File recodPath = new File(recordFloder, dataTimes + ".csv");
            if (!recodPath.exists()) {
                File[] listFiles = recordFloder.listFiles();

                recodPath.createNewFile();
                csvFileOutStream = new FileOutputStream(recodPath, true);
                StringBuffer buffer = new StringBuffer();
                buffer.append("时间").append(",").append("文件名称").append(",").append("群数量").append(",").append("总数量").append(System.lineSeparator());
                csvFileOutStream.write(buffer.toString().getBytes());
                csvFileOutStream.flush();
                executor.execute(() -> {
                    for (int i = 0; i < listFiles.length; i++) {
                        LocalDate preDate = localDateNow.plusMonths(-1);
                        LocalDate fileDate = LocalDate.parse(listFiles[i].getName().replace(".csv", ""), format);
                        if (preDate.isAfter(fileDate)) {
                            boolean secuess = listFiles[i].delete();
                            System.out.println("删除文件记录" + listFiles[i].getName() + "" + (secuess ? "成功!" : "失败!"));
                        }
                    }
                });
            } else {
                csvFileOutStream = new FileOutputStream(recodPath, true);
            }
        } catch (IOException e) {
            System.err.println(String.format("文件操作失败！->[%s]", e.getMessage()));
            int option = JOptionPane.showConfirmDialog(null, "打开/创建 文件失败,请检查文件是否被占用。\r\n【确定】将继续执行程序,文件不会保存;\r\n【取消】将退出程序。", "打开/创建 文件", JOptionPane.OK_CANCEL_OPTION);
            if (option != JOptionPane.OK_OPTION){
                System.exit(0);
            }
        }
    }

    public void run() {
        createMainWindow();
        createAdjustWindow();
        handleStatis(null);
    }

    private void handleStatis(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            if (tipsCheckBox.isSelected()) {
                JOptionPane.showMessageDialog(mainWindow, "请选择图片！", "请选择图片", JOptionPane.PLAIN_MESSAGE, new ImageIcon(rongLogoPath));
                return;
            } else {
                return;
            }
        }
        Mat srcMat = Imgcodecs.imread(filePath, Imgcodecs.IMREAD_COLOR);
        Mat resizeMat = new Mat();
        double rotio = Math.min((viewPortWidth / 3.0) / srcMat.width(), viewPortHeight / srcMat.height());
        Imgproc.resize(srcMat, resizeMat, new Size(srcMat.width() * rotio, srcMat.height() * rotio));
        //        Mat dstMat = Mat.zeros(srcMat.size(), CvType.CV_8UC3);
//        Mat dstMat = new Mat(srcMat.size(), CvType.CV_8UC3, new Scalar(128, 128, 128));

        /*均值飘移*/
//        Imgproc.pyrMeanShiftFiltering(srcMat,srcMat,30,30);
//        HighGui.imshow("meanshift", srcMat);
//        HighGui.waitKey(1);

        /*灰度图*/
        Mat grayMat = new Mat();
        Imgproc.cvtColor(resizeMat, grayMat, Imgproc.COLOR_BGR2GRAY);
//        HighGui.imshow("gray", grayMat);
//
//        Mat histMat= new Mat();
//        Imgproc.equalizeHist(grayMat,grayMat);
//        HighGui.imshow("hist", grayMat);
//
//        CLAHE clahe = Imgproc.createCLAHE();
//        Mat claheMat = new Mat();
//        clahe.apply(grayMat,grayMat);
//        HighGui.imshow("clahe", claheMat);
//        HighGui.waitKey(1);



        /*检测圆形掩膜*/
        Mat circlesMat = new Mat();
        Mat maskMat = Mat.zeros(grayMat.size(), CvType.CV_8UC1);
        Mat displayMat = resizeMat.clone();
        Mat maskSrcMat = new Mat(grayMat.size(), CvType.CV_8UC3, new Scalar(105, 105, 105));
        Imgproc.HoughCircles(grayMat, circlesMat, Imgproc.HOUGH_GRADIENT, 1.0, 255, 255, 80, 100, 1000);
//        HighGui.imshow("circlesMat",circlesMat);
//        HighGui.waitKey(10);
        Rect roiRect = new Rect();
        Mat roiMat = resizeMat;
        if (circlesMat.cols() > 0) {
            for (int col = 0; col < circlesMat.cols(); col++) {
                double[] c = circlesMat.get(0, col);
                Point center = new Point(Math.round(c[0]), Math.round(c[1]));
                // circle center
                Imgproc.circle(displayMat, center, 1, new Scalar(0, 255, 0), 3, 8, 0);
                // circle outline
                Imgproc.putText(displayMat, String.format("%03d", col), new Point(center.x - 10, center.y + 3), Imgproc.FONT_HERSHEY_PLAIN, 0.5, new Scalar(255, 0, 255), 1, Imgproc.LINE_AA);
                int radius = (int) Math.round(c[2]);
                Imgproc.circle(displayMat, center, radius, new Scalar(0, 255, 0), 2, Imgproc.LINE_AA);
                Imgproc.circle(maskMat, center, radius, new Scalar(255, 255, 255), -1, Imgproc.LINE_AA);
                Imgproc.circle(resizeMat, center, radius, new Scalar(127, 0, 127), 2, Imgproc.LINE_AA);
                roiRect = new Rect((int) (center.x - radius * 1.1), (int) (center.y - radius * 1.1), (int) (radius * 2.2), (int) (radius * 2.2));
                break;
            }
            resizeMat.copyTo(maskSrcMat, maskMat);
            maskSrcMat.copyTo(resizeMat);
            roiMat = resizeMat.submat(roiRect);
        } else {
            if (tipsCheckBox.isSelected()) {
                String msg = "请注意：\r\n未检测到目标区域;\r\n按【确定】将检测所有位置,统计数量可能不准确;\r\n按【取消】可取消本次操作。";
                int option = JOptionPane.showConfirmDialog(mainWindow, msg, "提示", JOptionPane.WARNING_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
                if (option != JOptionPane.OK_OPTION) {
                    return;
                }
            }
        }
        Mat targetRoiMat = new Mat();

        double retio = Math.min((double) resizeMat.width() / roiMat.width(), (double) resizeMat.height() / roiMat.height());
        Imgproc.resize(roiMat, targetRoiMat, new Size(roiMat.width() * retio, roiMat.width() * retio));

        Mat dstMat = new Mat(targetRoiMat.size(), CvType.CV_8UC3, new Scalar(105, 105, 105));
//        HighGui.imshow("displayMat", displayMat);
//        HighGui.imshow("maskMat", maskMat);
//        HighGui.imshow("maskSrcMat", maskSrcMat);
//        HighGui.waitKey(1);

//        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2 * 5 + 1, 2 * 5 + 1));
//        Imgproc.morphologyEx(srcMat,srcMat,Imgproc.MORPH_OPEN,kernel);

        /*hsv颜色空间*/
        Mat hsvMat = new Mat();
        Imgproc.cvtColor(targetRoiMat, hsvMat, Imgproc.COLOR_BGR2HSV);


        /*inrang二值化*/
        Mat inrangMat = new Mat();
        Core.inRange(hsvMat, new Scalar(sliderLowH.getValue(), sliderLowS.getValue(), sliderLowV.getValue()),
                new Scalar(sliderHighH.getValue(), sliderHighS.getValue(), sliderHighV.getValue()), inrangMat);
        /*中值滤波*/
        Imgproc.medianBlur(inrangMat, inrangMat, 5);

        /*腐蚀膨胀*/
//        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2 * 5 + 1, 2 * 5 + 1));
//        Mat erodeMat = new Mat();
//        Imgproc.erode(srcMat, srcMat, kernel,new Point(-1,-1),2);
//        HighGui.imshow("erode",erodeMat);
//
//        Mat dilateMat = new Mat();
//        Imgproc.dilate(srcMat,dilateMat,kernel,new Point(-1,-1),5);
//        HighGui.imshow("dilate",erodeMat);
//        HighGui.waitKey(1);

        /*形态学操作*/
//        Mat openMat = new Mat();
//        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2 * 2 + 1, 2 * 2 + 1));
//        Imgproc.morphologyEx(srcMat, srcMat, Imgproc.MORPH_OPEN, kernel);
////        Imgproc.morphologyEx(srcMat, openMat, Imgproc.MORPH_OPEN, kernel);
//        HighGui.imshow("open", openMat);
//        HighGui.waitKey(1);


        /*距离转换 */
//        executor.execute(() -> {
//            Mat distanceMat = new Mat();
//            Imgproc.distanceTransform(inrangMat, distanceMat, Imgproc.CV_DIST_L1, 3);
//            Mat normDistanceMat = new Mat();
//            Core.normalize(distanceMat, normDistanceMat, 0.0, 1.0, Core.NORM_MINMAX);
//            Mat distDisplayScaled = new Mat();
//            Core.multiply(normDistanceMat, new Scalar(255), distDisplayScaled);
//            Mat distDisplay = new Mat();
//            distDisplayScaled.convertTo(distDisplay, CvType.CV_8U);
//            HighGui.imshow("distance", distDisplay);
//            HighGui.waitKey(1);
////            canvasShowImage("normDistanceMat", normDistanceMat);
//        });

        /*新方法直接求出 每一联通区域labels、外接矩形、面积、圆心*/
//        Mat labels = new Mat();
//        Mat stats = new Mat();
//        Mat centroids = new Mat();
////        int counts = Imgproc.connectedComponents(inrangMat, labels);
//        int counts = Imgproc.connectedComponentsWithStats(inrangMat, labels,stats,centroids);
//        System.out.println(counts);
//        System.out.println(labels.size());
//        Mat normMat = new Mat();
//        labels.convertTo(normMat,CvType.CV_8UC1);
//        Imgproc.equalizeHist(normMat,normMat);
//        HighGui.imshow("labels",normMat);
//        HighGui.waitKey(1);


        List<MatOfPoint> findContours = new ArrayList<>();
        Mat hierarchyMat = new Mat();
        Imgproc.findContours(inrangMat, findContours, hierarchyMat, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE);

//        Imgproc.polylines(srcMat, findContours, true, new Scalar(0,255,0), 1, Imgproc.LINE_AA, 0);
//        Imgproc.polylines(dstMat, findContours, true, new Scalar(0,255,0), 1, Imgproc.LINE_AA, 0);
//        AtomicInteger atomic = new AtomicInteger();
        AtomicInteger atomicTotal = new AtomicInteger();
        AtomicInteger atomicGrop = new AtomicInteger();
        for (int index = 0; index < findContours.size(); index++) {

            MatOfPoint contour = findContours.get(index);
            int[] hierarchyInts = new int[4];
            hierarchyMat.get(0, index, hierarchyInts);



            double area = Imgproc.contourArea(contour);
            int count = (int) Math.round(area / sliderStdArea.getValue());
//            MatOfPoint2f contour2f = new MatOfPoint2f(contour.toArray());
//            double length = Imgproc.arcLength(contour2f,true);
//            //            double ratio = area / (Math.pow(length / 4, 2) + 1e-5);
//            System.out.println(atomicGrop.get() + "->" + area + "/" + length + "=" + area / length);
            if(hierarchyInts[3] == -1){
                atomicGrop.incrementAndGet();
                atomicTotal.addAndGet(count);
            }else{
                atomicTotal.addAndGet(-count);
            }
//            count = hierarchyInts[3] != -1 ? -count : count;
//            MatOfPoint2f gray2f = new MatOfPoint2f(contour.toArray());
//            double length = Imgproc.arcLength(gray2f, true);

//            System.out.println(index + "->" + area + "/" + length + "=" + area / length);

            /*多边形拟合*/
//            MatOfPoint2f inputPolyMat = new MatOfPoint2f(findContours.get(index).toArray());
//            MatOfPoint2f resultPolyMat = new MatOfPoint2f();
//            Imgproc.approxPolyDP(inputPolyMat,resultPolyMat,3,true);
//            MatOfPoint resultPoint = new MatOfPoint(resultPolyMat.toArray());
//            Imgproc.drawContours(dstMat, new ArrayList<MatOfPoint>(){{add(resultPoint);}}, 0, new Scalar(160, 255, 0), 1, Imgproc.LINE_AA, hierarchy, 0, new Point());
//            Imgproc.drawContours(srcMat, new ArrayList<MatOfPoint>(){{add(resultPoint);}}, 0, new Scalar(0, 0, 255), 1, Imgproc.LINE_AA, hierarchy, 0, new Point());

            /* 计算中心(质心)*/
            Moments moments = Imgproc.moments(contour);
            /* 计算中心矩 */
            Point center = new Point(moments.get_m10() / moments.get_m00(), moments.get_m01() / moments.get_m00());


            Scalar randColor = new Scalar(this.randColor.nextInt(256), this.randColor.nextInt(256), this.randColor.nextInt(256));
            if (hierarchyInts[3] == -1) {
                Imgproc.circle(targetRoiMat, center, 1, new Scalar(0, 255, 0), 2, 8, 0);
                Imgproc.drawContours(targetRoiMat, findContours, index, new Scalar(160, 255, 0), 1, Imgproc.LINE_AA, hierarchyMat, 0, new Point());
                Imgproc.putText(targetRoiMat, index+ ":" +count, new Point(center.x - 15, center.y + 3), Imgproc.FONT_HERSHEY_PLAIN, 0.8, new Scalar(255, 60, 0), 1, Imgproc.LINE_AA);

                Imgproc.circle(dstMat, center, 1, randColor, 2, 8, 0);
                Imgproc.drawContours(dstMat, findContours, index, randColor, 2, Imgproc.LINE_AA, hierarchyMat, 0, new Point());
                Imgproc.putText(dstMat, String.valueOf(count), new Point(center.x - 5, center.y + 3), Imgproc.FONT_HERSHEY_PLAIN, 0.8, new Scalar(255, 255, 255), 1, Imgproc.LINE_AA);
            } else {
                Imgproc.circle(targetRoiMat, center, 1, new Scalar(47,79,79), 2, 8, 0);
                Imgproc.drawContours(targetRoiMat, findContours, index, new Scalar(47,79,79), 1, Imgproc.LINE_AA, hierarchyMat, 0, new Point());
                Imgproc.putText(targetRoiMat, -index + ":" + (-count), new Point(center.x - 15, center.y + 3), Imgproc.FONT_HERSHEY_PLAIN, 0.6, new Scalar(47,79,79), 1, Imgproc.LINE_AA);

                Imgproc.circle(dstMat, center, 1, randColor, 2, 8, 0);
                Imgproc.drawContours(dstMat, findContours, index, randColor, 2, Imgproc.LINE_AA, hierarchyMat, 0, new Point());
                Imgproc.putText(dstMat, String.valueOf(count), new Point(center.x - 5, center.y + 3), Imgproc.FONT_HERSHEY_PLAIN, 0.8, new Scalar(255, 255, 255), 1, Imgproc.LINE_AA);
            }
        }

        Imgproc.putText(targetRoiMat, "group:" + atomicGrop.get(), new Point(20, targetRoiMat.height() - 20), Imgproc.FONT_HERSHEY_COMPLEX, 0.6, new Scalar(255, 255, 255), 1, Imgproc.LINE_AA);
        Imgproc.putText(targetRoiMat, "total:" + atomicTotal.get(), new Point(20 + targetRoiMat.width() / 2, targetRoiMat.height() - 20), Imgproc.FONT_HERSHEY_COMPLEX, 0.6, new Scalar(255, 255, 255), 1, Imgproc.LINE_AA);

        Imgproc.putText(dstMat, "group:" + atomicGrop.get(), new Point(20, targetRoiMat.height() - 20), Imgproc.FONT_HERSHEY_COMPLEX, 0.6, new Scalar(255, 255, 255), 1, Imgproc.LINE_AA);
        Imgproc.putText(dstMat, "total:" + atomicTotal.get(), new Point(20 + targetRoiMat.width() / 2, targetRoiMat.height() - 20), Imgproc.FONT_HERSHEY_COMPLEX, 0.6, new Scalar(255, 255, 255), 1, Imgproc.LINE_AA);

        totalCountField.setText(atomicTotal.toString());
        groupCountField.setText(atomicGrop.toString());
        if (SwingUtilities.isEventDispatchThread()) {
            srcImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(targetRoiMat)));
            detectImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(inrangMat)));
            distImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(dstMat)));
            mainWindow.repaint();
        } else {
            SwingUtilities.invokeLater(() -> {
                srcImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(targetRoiMat)));
                detectImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(inrangMat)));
                distImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(dstMat)));
                mainWindow.repaint();
            });
        }

        if (recordCheckBox.isSelected()) {
                 executor.execute(() -> {
                StringBuffer rowBuf = new StringBuffer();
                rowBuf.append(LocalDateTime.now().format(dateTimeFormatter)).append(",");
                rowBuf.append(filePath).append(",").append(atomicGrop.toString()).append(",").append(atomicTotal.toString()).append(System.lineSeparator());
                try {
                    csvFileOutStream.write(rowBuf.toString().getBytes());
                    csvFileOutStream.flush();
                } catch (IOException e) {
                    System.out.println(LocalDateTime.now().toString() + " : " + e.getMessage());
                }
            });
        }
        if (tipsCheckBox.isSelected() && findContours.size() <= 0) {
            JOptionPane.showMessageDialog(mainWindow, "未检测到目标,请根据图片调整参数设置！", "提示", JOptionPane.WARNING_MESSAGE);
        }
    }


    private void createMainWindow() {

        mainWindow = new JFrame(MAIN_WINDOW);
        mainWindow.setPreferredSize(new Dimension((int) viewPortWidth, (int) viewPortHeight));
        Container containerPanel = mainWindow.getContentPane();

        mainWindow.setIconImage(scaledIcon);
//        window.setUndecorated(true); // 去掉窗口的装饰
//        window.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);//采用指定的窗口装饰风格
        mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JMenu fileMenu = mainMenuBar.createFileMenu();
        mainMenuBar.add(fileMenu);
//        JMenu editMenu = mainMenuBar.createEditMenu();
//        mainMenuBar.add(editMenu);
        JMenu optionMenu = mainMenuBar.createOptionMenu();
        mainMenuBar.add(optionMenu);
        JPopupMenu popupMenu = mainMenuBar.createPopupMenu();
        popupMenu.setVisible(false);
        mainWindow.setJMenuBar(mainMenuBar);
        mainMenuBar.setVisible(true);


        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());


        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(new BorderLayout());
        titlePanel.setBackground(Color.WHITE);
//        titlePanel.setBorder(BorderFactory.createLineBorder(Color.darkGray, 2));
        JLabel titleLabel = new JLabel(MAIN_WINDOW, JLabel.CENTER);
        titleLabel.setBorder(BorderFactory.createEmptyBorder(20, 0, 10, 0));
        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        titleLabel.setFont(new Font("黑体", Font.BOLD, 24));
        titlePanel.add(titleLabel, BorderLayout.NORTH);

        JLabel subtitleLabel = new JLabel(company, JLabel.CENTER);
        subtitleLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0));
        subtitleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        subtitleLabel.setFont(new Font("楷体", Font.BOLD, 16));
        titlePanel.add(subtitleLabel, BorderLayout.CENTER);

        topPanel.add(titlePanel, BorderLayout.NORTH);

        containerPanel.add(topPanel, BorderLayout.NORTH);

        JPanel centrePanel = new JPanel();
        centrePanel.setLayout(new BorderLayout());
        centrePanel.setBorder(BorderFactory.createTitledBorder("图片处理"));

        JPanel statePanel = new JPanel();
        statePanel.setLayout(new BorderLayout());
//        statePanel.setBackground(Color.LIGHT_GRAY);
        JPanel leftStatePanel = new JPanel();
        leftStatePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
        leftStatePanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
        JLabel currentPathLabel = new JLabel("当前文件路径：");
        leftStatePanel.add(currentPathLabel);


//        currentPathField = new JTextField(defaultFilename, 60);
//        Stack recentFileStack = new Stack();
//        recentFileStack.add(0, currentPathComboBox);
        currentPathComboBox = new JComboBox();
        currentPathComboBox.setEditable(true);
        currentPathComboBox.addItemListener(e -> {
                    handleFileButton.setEnabled(currentPathComboBox.getSelectedItem()!=null);
        });
//        currentPathComboBox.setPreferredSize(new Dimension(screen.width/6,30));
        currentPathComboBox.setPrototypeDisplayValue("==================DisplayLength===================");
        currentPathComboBox.setMaximumRowCount(10);
//        currentPathComboBox.addItem(defaultFilename);

        leftStatePanel.add(currentPathComboBox);


        chooseFileButton = new JButton("选择文件");
        chooseFileButton.setFont(new Font("宋体", Font.BOLD, 12));
        chooseFileButton.addActionListener(fileOptionListener);
        leftStatePanel.add(chooseFileButton);

        handleFileButton = new JButton("开始处理");
        handleFileButton.setForeground(new Color(100,100,255));
//        handleFileButton.setBorder(BorderFactory.createLineBorder(Color.blue));
//        handleFileButton.setBackground(new Color(200,240,200));
        handleFileButton.setEnabled(currentPathComboBox.getSelectedItem()!=null);
        handleFileButton.setFont(new Font("宋体", Font.BOLD, 12));
        handleFileButton.addActionListener(fileOptionListener);
        leftStatePanel.add(handleFileButton);

        statePanel.add(leftStatePanel, BorderLayout.WEST);

        JPanel rightStatePanel = new JPanel();
        rightStatePanel.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
        rightStatePanel.setLayout(new FlowLayout(FlowLayout.RIGHT));


        JLabel groupCountLabel = new JLabel("组数量：");
        rightStatePanel.add(groupCountLabel);
        groupCountField = new JTextField(10);
        groupCountField.setEditable(false);
        rightStatePanel.add(groupCountField);

        JLabel totalCountLabel = new JLabel("总数量：");
        rightStatePanel.add(totalCountLabel);
        totalCountField = new JTextField(10);
        totalCountField.setEditable(false);
//        totalCountField.setBorder(BorderFactory.createEmptyBorder(0,0,0,20));
        rightStatePanel.add(totalCountField);

        tipsCheckBox = new JCheckBox();
        tipsCheckBox.setSelected(false);
        rightStatePanel.add(tipsCheckBox);
        JLabel tipsLabel = new JLabel("是否提示");
        rightStatePanel.add(tipsLabel);

        recordCheckBox = new JCheckBox();
        recordCheckBox.setSelected(false);
        rightStatePanel.add(recordCheckBox);
        JLabel recordLabel = new JLabel("保存记录");
        rightStatePanel.add(recordLabel);


        statePanel.add(rightStatePanel, BorderLayout.EAST);
        JSeparator separator = new JSeparator(SwingConstants.CENTER);
        separator.setPreferredSize(new Dimension(mainWindow.getWidth(), 2));
        separator.setBackground(Color.lightGray);
        statePanel.add(separator, BorderLayout.SOUTH);

        centrePanel.add(statePanel, BorderLayout.NORTH);

//     Mat matFrame = Imgcodecs.imread(defaultFilename, Imgcodecs.IMREAD_COLOR);
//        Imgproc.resize(matFrame, matFrame, new Size(matFrame.width() , matFrame.height() ));
//        Image img = HighGui.toBufferedImage(matFrame);

        JPanel srcImagePanel = new JPanel(new BorderLayout());
        Mat srcMat = new Mat((int) viewPortHeight, (int) (viewPortWidth / 3.0), CvType.CV_8UC3, new Scalar(255, 206, 135));
        Imgproc.putText(srcMat, "src", new Point(srcMat.width() / 2 - 20, srcMat.height() / 2 - 10), Imgproc.FONT_HERSHEY_TRIPLEX, 1.0, new Scalar(255, 255, 255), 3, Imgproc.LINE_AA);
        srcImageLabel = new JLabel(new ImageIcon(HighGui.toBufferedImage(srcMat)), JLabel.CENTER);
        srcImagePanel.add(srcImageLabel);
        centrePanel.add(srcImagePanel, BorderLayout.WEST);

        Mat detectMat = Mat.zeros(srcMat.size(), CvType.CV_8UC1);
        Imgproc.putText(detectMat, "detect", new Point(srcMat.width() / 2 - 40, srcMat.height() / 2 - 10), Imgproc.FONT_HERSHEY_TRIPLEX, 1.0, new Scalar(255, 255, 255), 3, Imgproc.LINE_AA);
        detectImageLabel = new JLabel(new ImageIcon(HighGui.toBufferedImage(detectMat)));
        centrePanel.add(detectImageLabel, BorderLayout.CENTER);

        Mat destMat = new Mat(srcMat.size(), CvType.CV_8UC3, new Scalar(127, 127, 127));
        Imgproc.putText(destMat, "dest", new Point(srcMat.width() / 2 - 30, srcMat.height() / 2 - 10), Imgproc.FONT_HERSHEY_TRIPLEX, 1.0, new Scalar(255, 255, 255), 2, Imgproc.LINE_AA);

        distImageLabel = new JLabel(new ImageIcon(HighGui.toBufferedImage(destMat)));

        centrePanel.add(distImageLabel, BorderLayout.EAST);

//        JPanel progressPanel = new JPanel();
        Box progressBox = Box.createHorizontalBox();
        progressBox.setBorder(BorderFactory.createEmptyBorder(5,0,3,0));
        progressBox.add(new JLabel("进度："));
        progressBox.add(Box.createHorizontalStrut(5));
        progressLabel = new JLabel("0/0");
        progressBox.add(progressLabel);
        progressBox.add(Box.createHorizontalStrut(10));

        progressBar = new JProgressBar();
        // 设置进度的 最小值 和 最大值
        progressBar.setMinimum(0);
        progressBar.setMaximum(100);
        // 设置当前进度值
        progressBar.setValue(0);
        // 绘制百分比文本（进度条中间显示的百分数）
        progressBar.setStringPainted(true);
        progressBox.add(progressBar);

        centrePanel.add(progressBox, BorderLayout.SOUTH);

        containerPanel.add(centrePanel, BorderLayout.CENTER);

        Panel bottomPanel = new Panel();
        bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
        JLabel copyrightLabel = new JLabel();

        copyrightLabel.setIcon(new ImageIcon(scaledIcon));
        copyrightLabel.setText(copyrightInfo);
        bottomPanel.add(copyrightLabel);
        containerPanel.add(bottomPanel, BorderLayout.SOUTH);

        mainWindow.addMouseListener(popupMenuMouseListener);
        mainWindow.setAutoRequestFocus(true);
        mainWindow.setResizable(true);
        mainWindow.pack();
        mainWindow.setLocationRelativeTo(null);//居中显示
//        mainWindow.setExtendedState(JFrame.MAXIMIZED_BOTH);//全屏
        mainWindow.setVisible(true);
    }

    private void createAdjustWindow() {
//        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
//        adjustWindow = new JFrame(ADJUST_WINDOW);
        adjustWindow = new JDialog(mainWindow, ADJUST_WINDOW, Dialog.ModalityType.DOCUMENT_MODAL);

        adjustWindow.setPreferredSize(new Dimension((int) (viewPortWidth * 0.7), (int) (viewPortHeight * 0.6)));
        Container contentPane = adjustWindow.getContentPane();
        ImageIcon icon = new ImageIcon(rongLogoPath);
        adjustWindow.setIconImage(icon.getImage());
//        window.setUndecorated(true); // 去掉窗口的装饰
//        window.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);//采用指定的窗口装饰风格
        adjustWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);


        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());


        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(new BorderLayout());
        JLabel titleLabel = new JLabel(ADJUST_WINDOW, JLabel.CENTER);
        titleLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        titleLabel.setFont(new Font("黑体", Font.BOLD, 16));
        titlePanel.add(titleLabel, BorderLayout.NORTH);

        JLabel subtitleLabel = new JLabel(company, JLabel.CENTER);
        subtitleLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
        subtitleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        subtitleLabel.setFont(new Font("楷体", Font.BOLD, 12));
        titlePanel.add(subtitleLabel, BorderLayout.CENTER);

        topPanel.add(titlePanel, BorderLayout.NORTH);

        contentPane.add(topPanel, BorderLayout.NORTH);

        JPanel sliderPanel = new JPanel();
        sliderPanel.setBorder(BorderFactory.createTitledBorder("参数调整"));
        sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.PAGE_AXIS));

        Box lowHBox = Box.createHorizontalBox();
        lowHBox.add(Box.createHorizontalStrut(20));
        lowHBox.add(new JLabel(LOW_H_NAME));
        sliderLowH = new JSlider(0, MAX_VALUE_H, 10);
        sliderLowH.setMajorTickSpacing(10);
        sliderLowH.setMinorTickSpacing(2);
        sliderLowH.setPaintTicks(true);
        sliderLowH.setPaintLabels(true);
        lowHBox.add(sliderLowH);
        lowHBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(lowHBox);

        Box highHBox = Box.createHorizontalBox();
        highHBox.add(Box.createHorizontalStrut(20));
        highHBox.add(new JLabel(HIGH_H_NAME));
        sliderHighH = new JSlider(0, MAX_VALUE_H, 40);
        sliderHighH.setMajorTickSpacing(10);
        sliderHighH.setMinorTickSpacing(2);
        sliderHighH.setPaintTicks(true);
        sliderHighH.setPaintLabels(true);
        highHBox.add(sliderHighH);
        highHBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(highHBox);

        Box lowSBox = Box.createHorizontalBox();
        lowSBox.add(Box.createHorizontalStrut(20));
        lowSBox.add(new JLabel(LOW_S_NAME));
        sliderLowS = new JSlider(0, MAX_VALUE, 100);
        sliderLowS.setMajorTickSpacing(10);
        sliderLowS.setMinorTickSpacing(2);
        sliderLowS.setPaintTicks(true);
        sliderLowS.setPaintLabels(true);
        lowSBox.add(sliderLowS);
        lowSBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(lowSBox);

        Box highSBox = Box.createHorizontalBox();
        highSBox.add(Box.createHorizontalStrut(20));
        highSBox.add(new JLabel(HIGH_S_NAME));
        sliderHighS = new JSlider(0, MAX_VALUE, 200);
        sliderHighS.setMajorTickSpacing(10);
        sliderHighS.setMinorTickSpacing(2);
        sliderHighS.setPaintTicks(true);
        sliderHighS.setPaintLabels(true);
        highSBox.add(sliderHighS);
        highSBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(highSBox);

        Box lowVBox = Box.createHorizontalBox();
        lowVBox.add(Box.createHorizontalStrut(20));
        lowVBox.add(new JLabel(LOW_V_NAME));
        sliderLowV = new JSlider(0, MAX_VALUE, 100);
        sliderLowV.setMajorTickSpacing(10);
        sliderLowV.setMinorTickSpacing(5);
        sliderLowV.setPaintTicks(true);
        sliderLowV.setPaintLabels(true);
        lowVBox.add(sliderLowV);
        lowVBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(lowVBox);

        Box highVBox = Box.createHorizontalBox();
        highVBox.add(Box.createHorizontalStrut(20));
        highVBox.add(new JLabel(HIGH_V_NAME));
        sliderHighV = new JSlider(0, MAX_VALUE, 255);
        sliderHighV.setMajorTickSpacing(10);
        sliderHighV.setMinorTickSpacing(5);
        sliderHighV.setPaintTicks(true);
        sliderHighV.setPaintLabels(true);
        highVBox.add(sliderHighV);
        highVBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(highVBox);

        Box stdAreaBox = Box.createHorizontalBox();
        stdAreaBox.add(Box.createHorizontalStrut(20));
        stdAreaBox.add(new JLabel(STD_AREA));
        sliderStdArea = new JSlider(0, 500, 300);
        sliderStdArea.setMajorTickSpacing(100);
        sliderStdArea.setMinorTickSpacing(10);
        sliderStdArea.setPaintTicks(true);
        sliderStdArea.setPaintLabels(true);
        stdAreaBox.add(sliderStdArea);
        stdAreaBox.add(Box.createHorizontalStrut(20));
        sliderPanel.add(stdAreaBox);

//        sliderLowH.addChangeListener(changeListener);
//        sliderHighH.addChangeListener(changeListener);
//        sliderLowS.addChangeListener(changeListener);
//        sliderHighS.addChangeListener(changeListener);
//        sliderLowV.addChangeListener(changeListener);
//        sliderHighV.addChangeListener(changeListener);
//        sliderStdArea.addChangeListener(changeListener);

        sliderLowH.addMouseListener(mouseAdapter);
        sliderHighH.addMouseListener(mouseAdapter);
        sliderLowS.addMouseListener(mouseAdapter);
        sliderHighS.addMouseListener(mouseAdapter);
        sliderLowV.addMouseListener(mouseAdapter);
        sliderHighV.addMouseListener(mouseAdapter);
        sliderStdArea.addMouseListener(mouseAdapter);

        contentPane.add(sliderPanel, BorderLayout.CENTER);


        Panel bottomPanel = new Panel();
        bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
//        JTextArea bottomCopyrightTextPane = new JTextArea();
//        bottomCopyrightTextPane.setLayout(new FlowLayout(FlowLayout.CENTER));
//        bottomCopyrightTextPane.setEditable(false);
        JLabel copyrightLabel = new JLabel();
        Image scaledIcon = icon.getImage().getScaledInstance(icon.getIconWidth() / 3, icon.getIconHeight() / 3, Image.SCALE_DEFAULT);
        icon.setImage(scaledIcon);
        copyrightLabel.setIcon(icon);
        copyrightLabel.setText(copyrightInfo);
        bottomPanel.add(copyrightLabel);
        contentPane.add(bottomPanel, BorderLayout.SOUTH);


        adjustWindow.setAutoRequestFocus(true);
//        adjustWindow.setAlwaysOnTop(true);
        adjustWindow.setResizable(false);
        adjustWindow.pack();
        adjustWindow.setLocation((int) (screenSize.getWidth() / 2 - adjustWindow.getWidth() / 2), (int) (screenSize.height - adjustWindow.getHeight() * 1.1));
//        adjustWindow.setLocationRelativeTo(mainWindow);//居中显示
        adjustWindow.setVisible(false);
    }

    private void update(Mat imgCapture, Mat imgThresh) {
        srcImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(imgCapture)));
        detectImageLabel.setIcon(new ImageIcon(HighGui.toBufferedImage(imgThresh)));
        mainWindow.repaint();
    }


    private class MainMenuBar extends JMenuBar {


        //定义“文件”菜单
        private JMenu createFileMenu() {
            JMenu fileMenu = new JMenu("文件(F)");
            fileMenu.setMnemonic(KeyEvent.VK_F);    //设置快速访问符
            JMenuItem createMenuItem = new JMenuItem("新建(N)", KeyEvent.VK_N);
            createMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
            fileMenu.add(createMenuItem);
            createMenuItem.setEnabled(false);

            chooseMenuItem = new JMenuItem("打开(O)", KeyEvent.VK_O);
            chooseMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
            chooseMenuItem.addActionListener(fileOptionListener);
            fileMenu.add(chooseMenuItem);

            JMenuItem saveFileMenuItem = new JMenuItem("保存(S)", KeyEvent.VK_S);
            saveFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
            saveFileMenuItem.setEnabled(false);
            fileMenu.add(saveFileMenuItem);
            fileMenu.addSeparator();
            exitMunuItem = new JMenuItem("退出(E)", KeyEvent.VK_E);
            exitMunuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.CTRL_MASK));
            exitMunuItem.addActionListener(fileOptionListener);
            fileMenu.add(exitMunuItem);
            return fileMenu;
        }


        //定义“编辑”菜单
        private JMenu createEditMenu() {
            JMenu editMenu = new JMenu("编辑(E)");
            editMenu.setMnemonic(KeyEvent.VK_E);
            editMenu.setEnabled(true);
            JMenuItem undoMenuItem = new JMenuItem("撤销(U)", KeyEvent.VK_U);
            undoMenuItem.setEnabled(false);
            editMenu.add(undoMenuItem);
            editMenu.addSeparator();
            JMenuItem clipMenuItem = new JMenuItem("剪贴(T)", KeyEvent.VK_T);
            editMenu.add(clipMenuItem);
            clipMenuItem.setEnabled(false);

            JMenuItem copyMenuItem = new JMenuItem("复制(C)", KeyEvent.VK_C);
            editMenu.add(copyMenuItem);
            copyMenuItem.setEnabled(false);
            editMenu.addSeparator();
            JCheckBoxMenuItem autoMenuItem = new JCheckBoxMenuItem("自动换行");
            editMenu.add(autoMenuItem);
            autoMenuItem.setEnabled(false);
            return editMenu;
        }

        //定义“操作”菜单
        private JMenu createOptionMenu() {
            JMenu optionMenu = new JMenu("操作(O)");
            optionMenu.setMnemonic(KeyEvent.VK_O);    //设置快速访问符
            JMenuItem openOptionItem = new JMenuItem("检测参数调整(S)", KeyEvent.VK_O);
            openOptionItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
            openOptionItem.addActionListener(e -> adjustWindow.setVisible(true));
            optionMenu.add(openOptionItem);
            openOptionItem.setEnabled(true);
            optionMenu.addSeparator();
            handleOptionItem = new JMenuItem("开始处理(H)", KeyEvent.VK_H);
            handleOptionItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.CTRL_MASK));
            handleOptionItem.addActionListener(fileOptionListener);
            optionMenu.add(handleOptionItem);
            return optionMenu;
        }

        private JPopupMenu createPopupMenu() {
            adjustPopupMenu = new JPopupMenu("操作选项");    //创建jPopupMenuOne对象
            JLabel popuHeaderLabel = new JLabel("操作选项");
            popuHeaderLabel.setFont(new Font("宋体", Font.BOLD, 13));
            ImageIcon imageIcon = new ImageIcon(rongLogoPath);
            Image scaledIcon = imageIcon.getImage().getScaledInstance(imageIcon.getIconWidth() / 3, imageIcon.getIconHeight() / 3, Image.SCALE_DEFAULT);
            imageIcon.setImage(scaledIcon);
            popuHeaderLabel.setIcon(imageIcon);
            adjustPopupMenu.add(popuHeaderLabel);
            adjustPopupMenu.addSeparator();
            JMenuItem openOptionItem = new JMenuItem("检测参数调整(C)", KeyEvent.VK_O);
            openOptionItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
            openOptionItem.addActionListener(e -> adjustWindow.setVisible(true));
            adjustPopupMenu.add(openOptionItem);
            adjustPopupMenu.addSeparator();
            chooseFilePopuMenu = new JMenuItem("选择文件(O)", KeyEvent.VK_O);
            chooseFilePopuMenu.addActionListener(fileOptionListener);
            adjustPopupMenu.add(chooseFilePopuMenu);
            adjustPopupMenu.addSeparator();
            handleFilePopuMenu = new JMenuItem("开始处理(H)", KeyEvent.VK_H);
            handleFilePopuMenu.addActionListener(fileOptionListener);
            adjustPopupMenu.add(handleFilePopuMenu);
            return adjustPopupMenu;
        }
    }

    private class AdjustChangeListener implements ChangeListener {
        @Override
        public void stateChanged(ChangeEvent e) {
            executor.execute(() -> {
                Object selectedItem = currentPathComboBox.getSelectedItem();
                if (selectedItem == null || selectedItem.toString().trim().isEmpty()) {
                    JOptionPane.showMessageDialog(mainWindow, "请选择调试图片！", "请选择调试图片", JOptionPane.PLAIN_MESSAGE, new ImageIcon(rongLogoPath));
                    return;
                }else{
                    File currentFile = new File(selectedItem.toString().trim());
                    if (currentFile.isFile()) {
                        handleStatis(currentFile.getAbsolutePath());
                    }else {
                        handleStatis(currentFile.list()[0]);
                    }
                }
            });
        }
    }

    private class PopupMenuMouseListener extends MouseAdapter {

        public void mousePressed(MouseEvent e) {
            showPopupMenu(e);
        }

        public void mouseReleased(MouseEvent e) {
            showPopupMenu(e);
        }

        private void showPopupMenu(MouseEvent e) {
            if (e.isPopupTrigger()) {
                //如果当前事件与鼠标事件相关，则弹出菜单
                adjustPopupMenu.show(e.getComponent(), e.getX(), e.getY());
            }
        }
    }

    private class AdjustMouseAdapter extends MouseAdapter {
        @Override
        public void mouseReleased(MouseEvent e) {
            executor.execute(() -> {
                Object selectedItem = currentPathComboBox.getSelectedItem();
                if (selectedItem == null || selectedItem.toString().trim().isEmpty()) {
                    JOptionPane.showMessageDialog(mainWindow, "请选择调试图片！", "请选择调试图片", JOptionPane.PLAIN_MESSAGE, new ImageIcon(rongLogoPath));
                    return;
                }else{
                    File currentFile = new File(selectedItem.toString().trim());
                    if (currentFile.isFile()) {
                        progressBar.setMinimum(0);
                        progressBar.setMaximum(1);
                        progressBar.setValue(0);
                        handleStatis(currentFile.getAbsolutePath());
                        progressBar.setValue(1);
                    }else {
                        progressBar.setMinimum(0);
                        progressBar.setMaximum(1);
                        progressBar.setValue(0);
                        handleStatis(currentFile.list()[0]);
                        progressBar.setValue(1);
                    }
                }
            });
        }
    }

    private class FileOptionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            Object source = event.getSource();
            if (source.equals(handleFileButton) || source.equals(handleFilePopuMenu)||source.equals(handleOptionItem)) {
                Object selectedItem = currentPathComboBox.getSelectedItem();
                if (selectedItem == null || selectedItem.toString().trim().isEmpty()) {
                    JOptionPane.showMessageDialog(mainWindow, "请选择图片！", "请选择图片", JOptionPane.PLAIN_MESSAGE, new ImageIcon(rongLogoPath));
                    return;
                }
                File currentFile = new File(selectedItem.toString().trim());
                if (currentFile.isFile()) {
                    executor.execute(()->{
                        progressBar.setMinimum(0);
                        progressBar.setMaximum(1);
                        progressBar.setValue(0);
                        progressLabel.setText("0/1");
                        handleStatis(currentFile.getAbsolutePath());
                        progressBar.setValue(1);
                        progressLabel.setText("1/1");
                    });
                } else if (currentFile.isDirectory()) {
                    executor.execute(() -> {
                        File[] files = currentFile.listFiles((dir, name) -> name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".jpeg"));
                        progressBar.setMinimum(0);
                        progressBar.setMaximum(files.length);
                        for (int i = 0; i < files.length; i++) {
                            System.out.println(files[i].getAbsolutePath());
                            handleStatis(files[i].getAbsolutePath());
                            progressBar.setValue(i+1);
                            progressLabel.setText((i+1)+"/"+files.length);
                            try {
                                TimeUnit.MILLISECONDS.sleep(200);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            } else if (source.equals(chooseMenuItem) || source.equals(chooseFilePopuMenu) || source.equals(chooseFileButton)) {
                int val = fileChooser.showOpenDialog(mainWindow);    //文件打开对话框
                if (val == fileChooser.APPROVE_OPTION) {
                    //正常选择文件
//                    File selectedFile = fileChooser.getSelectedFile();
                    if (currentPathComboBox.getItemCount() > 20) {
                        currentPathComboBox.removeItemAt(currentPathComboBox.getItemCount() - 1);
                    }
                    currentPathComboBox.insertItemAt(fileChooser.getSelectedFile().getAbsolutePath(), 0);
                    currentPathComboBox.setSelectedIndex(0);

                } else {
                    //未正常选择文件，如选择取消按钮
//                    currentPathComboBox.insertItemAt(defaultFilename,0);
//                    currentPathComboBox.setSelectedIndex(0);
                }
                handleFileButton.setEnabled(currentPathComboBox.getSelectedItem()!=null);
            } else if (source.equals(exitMunuItem)) {
                if (executor != null) {
                    executor.shutdown();
                }
                if (adjustWindow != null) {
                    adjustWindow.dispose();
                }
                if (mainWindow != null) {
                    mainWindow.dispose();
                }
                System.exit(0);
                Runtime.getRuntime().halt(0);
            }
        }
    }

    private class ImageFileFilter extends FileFilter {
        public String getDescription() {
            return "*.png;*.jpg;.jpeg";
        }

        public boolean accept(File file) {
            String name = file.getName().toLowerCase();
            return file.isDirectory() || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg");  // 仅显示目录和xls、xlsx文件
        }
    }

    public class ComboxStack<String> extends Stack {

    }

    private class HookThread extends Thread {
        @Override
        public void run() {
            if (csvFileOutStream != null) {
                try {
                    csvFileOutStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(">>>>>>> hook 退出程序！>>>>>> ");
        }
    }
}
